﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Equipment.Device.IO;
using RotovapPlatform.Domain.Equipment.Interfaces.Base;
using RotovapPlatform.Domain.Equipment.Interfaces.Services;

namespace RotovapPlatform.UI.ViewModels.DeviceMaintenance.ManualOperation
{
	/// <summary>
	/// IO模块手动操作视图模型
	/// </summary>
	public partial class ManualIOViewModel : ObservableObject, IDisposable
	{
		private readonly ILogger<ManualIOViewModel> _logger;
		private readonly IDeviceStatusService _deviceStatusService;
		private bool _disposed;

		/// <summary>
		/// 数字输入信号列表
		/// </summary>
		[ObservableProperty]
		private ObservableCollection<IOSignalItemViewModel> _diSignals = new();

		/// <summary>
		/// 数字输出信号列表
		/// </summary>
		[ObservableProperty]
		private ObservableCollection<IOSignalItemViewModel> _doSignals = new();

		/// <summary>
		/// 是否正在加载
		/// </summary>
		[ObservableProperty]
		private bool _isLoading;

		/// <summary>
		/// 构造函数
		/// </summary>
		public ManualIOViewModel(
			ILogger<ManualIOViewModel> logger,
			IDeviceStatusService deviceStatusService)
		{
			try
			{
				_logger = logger;
				_deviceStatusService = deviceStatusService;

				// 记录构造函数开始执行
				logger?.LogInformation("ManualIOViewModel开始初始化");

				// 如果设备服务不可用，则创建空列表但不抛出异常
				if (deviceStatusService == null)
				{
					logger?.LogWarning("IDeviceStatusService为null，将以离线模式运行");
					// 初始化空列表
					InitializeEmptySignalLists();
				}
				else
				{
					// 注册设备状态变化事件
					_deviceStatusService.DeviceStatusChanged += OnDeviceStatusChanged;
					logger?.LogInformation("已订阅DeviceStatusChanged事件");

					// 初始化信号列表
					InitializeSignalLists();
				}

				// 记录构造函数完成执行
				logger?.LogInformation("ManualIOViewModel初始化完成");
			}
			catch (Exception ex)
			{
				logger?.LogError(ex, "ManualIOViewModel初始化失败");
				// 初始化空列表确保UI可以显示
				InitializeEmptySignalLists();
			}
		}

		/// <summary>
		/// 初始化空的信号列表（离线模式）
		/// </summary>
		private void InitializeEmptySignalLists()
		{
			// 清空现有列表
			DiSignals.Clear();
			DoSignals.Clear();

			// 添加一些示例信号
			DiSignals.Add(new IOSignalItemViewModel
			{
				Id = "DI1-1",
				Description = "蒸发瓶位置传感器",
				SignalName = "DI1-1",
				IsOn = false
			});

			DiSignals.Add(new IOSignalItemViewModel
			{
				Id = "DI1-2",
				Description = "提升机上限位传感器",
				SignalName = "DI1-2",
				IsOn = false
			});

			DoSignals.Add(new IOSignalItemViewModel
			{
				Id = "DO1-1",
				Description = "冷凝管加液两通阀门1",
				SignalName = "DO1-1",
				IsOn = false
			});

			DoSignals.Add(new IOSignalItemViewModel
			{
				Id = "DO1-2",
				Description = "冷凝管加液两通阀门2",
				SignalName = "DO1-2",
				IsOn = false
			});

			_logger?.LogInformation("已初始化示例信号列表（离线模式）");
		}

		/// <summary>
		/// 初始化信号列表
		/// </summary>
		private void InitializeSignalLists()
		{
			try
			{
				// 初始化DI信号列表
				DiSignals.Clear();
				foreach (DISignalId id in Enum.GetValues(typeof(DISignalId)))
				{
					var signal = _deviceStatusService.GetDISignal(id);
					string description = GetSignalDescription(id);
					DiSignals.Add(new IOSignalItemViewModel
					{
						Id = id.ToString(),
						Description = description,
						SignalName = IOSignalUtils.GetDISignalName(id),
						IsOn = signal?.State ?? false,
						SignalId = id
					});
				}

				// 初始化DO信号列表
				DoSignals.Clear();
				foreach (DOSignalId id in Enum.GetValues(typeof(DOSignalId)))
				{
					var signal = _deviceStatusService.GetDOSignal(id);
					string description = GetSignalDescription(id);
					DoSignals.Add(new IOSignalItemViewModel
					{
						Id = id.ToString(),
						Description = description,
						SignalName = IOSignalUtils.GetDOSignalName(id),
						IsOn = signal?.State ?? false,
						SignalId = id
					});
				}
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "初始化IO信号列表失败");
			}
		}

		/// <summary>
		/// 获取信号描述
		/// </summary>
		private string GetSignalDescription(Enum signalId)
		{
			// 使用反射获取枚举项的描述（Summary特性）
			var fieldInfo = signalId.GetType().GetField(signalId.ToString());
			if (fieldInfo == null) return string.Empty;

			var attributes = (System.ComponentModel.DescriptionAttribute[])fieldInfo.GetCustomAttributes(
				typeof(System.ComponentModel.DescriptionAttribute), false);

			if (attributes != null && attributes.Length > 0)
			{
				return attributes[0].Description;
			}

			// 如果没有Description特性，尝试从XML注释中解析
			// 这里可以添加从XML文档中读取注释的逻辑
			// 简单起见，我们使用一个字典来映射

			// DI信号描述映射
			if (signalId is DISignalId diId)
			{
				var diDescriptions = new Dictionary<DISignalId, string>
				{
					{ DISignalId.EvaporateFlaskLevelSensor, "蒸发瓶液位传感器" },
					{ DISignalId.PushRodExtendLimitSensor, "推杆伸出限位传感器" },
					{ DISignalId.PushRodRetractLimitSensor, "推杆缩回限位传感器" },
					{ DISignalId.CondenserLevelSensor, "冷凝器液位传感器" },
					{ DISignalId.OilReplenishLevelSensor1, "补油输液液位传感器1" },
					{ DISignalId.OilReplenishLevelSensor2, "补油输液液位传感器2" },
					{ DISignalId.WasteBottleLevelSensor, "废液瓶液位传感器" },
					{ DISignalId.EmergencyStop, "急停" },
					{ DISignalId.Reset, "复位" },
					{ DISignalId.DoorSwitch1, "门磁开关1" },
					{ DISignalId.DoorSwitch2, "门磁开关2" },
					{ DISignalId.DoorSwitch3, "门磁开关3" },
					{ DISignalId.DoorSwitch4, "门磁开关4" },
					{ DISignalId.DoorSwitch5, "门磁开关5" },
					{ DISignalId.DoorSwitch6, "门磁开关6" },
					{ DISignalId.GripperLimitSwitch1, "关爪限位开关1" },
					{ DISignalId.GripperLimitSwitch2, "关爪限位开关2" }
				};

				if (diDescriptions.TryGetValue(diId, out string description))
				{
					return description;
				}

				// 备用信号处理
				if (diId.ToString().StartsWith("Reserved_"))
				{
					return "备用";
				}
			}

			// DO信号描述映射
			if (signalId is DOSignalId doId)
			{
				var doDescriptions = new Dictionary<DOSignalId, string>
				{
					{ DOSignalId.CondenserAddLiquidValve1, "冷凝管加液两通阀门1" },
					{ DOSignalId.CondenserAddLiquidValve2, "冷凝管加液两通阀门2" },
					{ DOSignalId.CondenserWashLiquidValve, "冷凝管洗液两通阀门" },
					{ DOSignalId.EvaporateFlaskCleanValve, "蒸发瓶清洗两通阀门" },
					{ DOSignalId.ExhaustCondensateLiquidValve, "排冷凝液两通阀门" },
					{ DOSignalId.CondensateRecycleValve, "冷凝液回收两通阀门" },
					{ DOSignalId.CondensateRecycleThreeWayValve, "冷凝液回收三通阀门" },
					{ DOSignalId.FeedingLiquidValve1, "进液台两通阀1" },
					{ DOSignalId.FeedingLiquidValve2, "进液台两通阀2" },
					{ DOSignalId.ExtractionLiquidValve, "取液模块两通阀" },
					{ DOSignalId.WashingLiquidBucketThreeWayValve, "洗液桶三通阀" },
					{ DOSignalId.WashingThreeWayValve1, "清洗三通阀1" },
					{ DOSignalId.WashingThreeWayValve2, "清洗三通阀2" },
					{ DOSignalId.PushRodExtendDirection, "推杆伸缩控制方向" },
					{ DOSignalId.DaylightLampSwitch, "日光灯开关/双路继电器" },
					{ DOSignalId.VacuumPumpControl, "真空泵启停控制/双路继电器" },
					{ DOSignalId.TriColorLamp_Red, "三色灯-红/单路继电器" },
					{ DOSignalId.TriColorLamp_Yellow, "三色灯-黄/单路继电器" },
					{ DOSignalId.TriColorLamp_Green, "三色灯-绿/单路继电器" },
					{ DOSignalId.Buzzer, "蜂鸣器/单路继电器" },
					{ DOSignalId.PushRodExtendControl, "推杆伸缩控制/单路继电器" }
				};

				if (doDescriptions.TryGetValue(doId, out string description))
				{
					return description;
				}

				// 备用信号处理
				if (doId.ToString().StartsWith("Reserved_"))
				{
					return "备用";
				}
			}

			return signalId.ToString();
		}

		/// <summary>
		/// 设备状态变化事件处理
		/// </summary>
		private void OnDeviceStatusChanged(object sender, DeviceStatusEventArgs e)
		{
			try
			{
				_logger?.LogDebug($"接收到设备状态变化事件: DeviceId={e.DeviceId}, Status={e.Status}");

				// 使用UI线程调度器确保在UI线程上更新控件
				App.Current.Dispatcher.Invoke(() =>
				{
					// 处理IO信号状态变化
					if (e.DeviceId.StartsWith("DI") && IOSignalUtils.TryParseDISignalId(e.DeviceId, out DISignalId diId))
					{
						// 更新DI信号状态
						var signalItem = DiSignals.FirstOrDefault(s => s.SignalId.Equals(diId));
						if (signalItem != null)
						{
							signalItem.IsOn = (bool)e.Status;
							_logger?.LogDebug($"已更新DI信号状态: {e.DeviceId}={e.Status}");
						}
						else
						{
							_logger?.LogWarning($"未找到匹配的DI信号: {e.DeviceId}");
						}
					}
					else if (e.DeviceId.StartsWith("DO") && IOSignalUtils.TryParseDOSignalId(e.DeviceId, out DOSignalId doId))
					{
						// 更新DO信号状态
						var signalItem = DoSignals.FirstOrDefault(s => s.SignalId.Equals(doId));
						if (signalItem != null)
						{
							signalItem.IsOn = (bool)e.Status;
							_logger?.LogDebug($"已更新DO信号状态: {e.DeviceId}={e.Status}");
						}
						else
						{
							_logger?.LogWarning($"未找到匹配的DO信号: {e.DeviceId}");
						}
					}
				});
			}
			catch (Exception ex)
			{
				_logger?.LogError(ex, $"处理设备状态变化事件异常: {e.DeviceId}");
			}
		}

		/// <summary>
		/// 刷新IO信号命令
		/// </summary>
		[RelayCommand]
		private async Task RefreshIOSignals()
		{
			try
			{
				IsLoading = true;

				if (_deviceStatusService == null)
				{
					_logger?.LogWarning("设备服务不可用，无法刷新IO信号");
					return;
				}

				//await _deviceStatusService.UpdateAllDeviceStatusAsync();

				// 更新所有DI信号状态
				foreach (var signal in DiSignals)
				{
					if (signal.SignalId is DISignalId diId)
					{
						var diSignal = _deviceStatusService.GetDISignal(diId);
						signal.IsOn = diSignal?.State ?? false;
					}
				}

				// 更新所有DO信号状态
				foreach (var signal in DoSignals)
				{
					if (signal.SignalId is DOSignalId doId)
					{
						var doSignal = _deviceStatusService.GetDOSignal(doId);
						signal.IsOn = doSignal?.State ?? false;
					}
				}

				_logger?.LogInformation("IO信号刷新成功");
			}
			catch (Exception ex)
			{
				_logger?.LogError(ex, "刷新IO信号状态失败");
			}
			finally
			{
				IsLoading = false;
			}
		}

		/// <summary>
		/// 设置DO信号状态命令
		/// </summary>
		[RelayCommand]
		private async Task SetDOState(IOSignalItemViewModel signal)
		{
			if (signal == null)
			{
				return;
			}

			if (_deviceStatusService == null)
			{
				_logger?.LogWarning("设备服务不可用，无法设置DO信号状态");
				// 在离线模式下，只简单地切换信号状态用于演示
				signal.IsOn = !signal.IsOn;
				return;
			}

			// 如果是实际模式且有有效的信号ID
			if (signal.SignalId is DOSignalId doId)
			{
				try
				{
					IsLoading = true;
					bool result = _deviceStatusService.SetDOSignalStateAsync(doId, signal.IsOn).Result.Success;
					if (!result)
					{
						// 如果设置失败，恢复状态
						signal.IsOn = !signal.IsOn;
						_logger.LogWarning($"设置DO信号状态失败: {doId}");
					}
				}
				catch (Exception ex)
				{
					// 如果发生异常，恢复状态
					signal.IsOn = !signal.IsOn;
					_logger.LogError(ex, $"设置DO信号状态异常: {doId}");
				}
				finally
				{
					IsLoading = false;
				}
			}
		}

		/// <summary>
		/// 释放资源
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// 释放资源
		/// </summary>
		/// <param name="disposing">是否为显式释放</param>
		protected virtual void Dispose(bool disposing)
		{
			if (_disposed) return;

			if (disposing)
			{
				// 取消订阅设备状态变化事件
				if (_deviceStatusService != null)
				{
					_deviceStatusService.DeviceStatusChanged -= OnDeviceStatusChanged;
					_logger?.LogInformation("ManualIOViewModel已取消订阅DeviceStatusChanged事件");
				}
			}

			_disposed = true;
		}

		/// <summary>
		/// 重新初始化ViewModel，用于视图重新加载时
		/// </summary>
		public void Reinitialize()
		{
			try
			{
				_logger?.LogInformation("正在重新初始化ManualIOViewModel");

				// 如果已释放，则重置状态
				if (_disposed)
				{
					_disposed = false;
				}

				// 确保事件已订阅
				if (_deviceStatusService != null)
				{
					// 先取消之前可能的订阅以避免重复
					_deviceStatusService.DeviceStatusChanged -= OnDeviceStatusChanged;

					// 重新订阅事件
					_deviceStatusService.DeviceStatusChanged += OnDeviceStatusChanged;
					_logger?.LogInformation("已重新订阅DeviceStatusChanged事件");
				}

				// 重新初始化信号列表
				if (_deviceStatusService != null)
				{
					InitializeSignalLists();
				}
				else
				{
					InitializeEmptySignalLists();
				}

				_logger?.LogInformation("ManualIOViewModel重新初始化完成");
			}
			catch (Exception ex)
			{
				_logger?.LogError(ex, "重新初始化ManualIOViewModel失败");
			}
		}
	}

	/// <summary>
	/// IO信号项视图模型
	/// </summary>
	public partial class IOSignalItemViewModel : ObservableObject
	{
		/// <summary>
		/// 信号标识符
		/// </summary>
		public string Id { get; set; }

		/// <summary>
		/// 信号描述
		/// </summary>
		public string Description { get; set; }

		/// <summary>
		/// 信号名称（如DI1-1）
		/// </summary>
		public string SignalName { get; set; }

		/// <summary>
		/// 信号状态
		/// </summary>
		[ObservableProperty]
		private bool _isOn;

		/// <summary>
		/// 信号ID（枚举值）
		/// </summary>
		public object SignalId { get; set; }
	}
}

